\section{GNSS satellite orbit determination and station network analysis}\label{cookbook.gnssNetwork}
This cookbook chapter describes an example of global GNSS processing as done by analysis centers of the
International GNSS Service (IGS). Resulting products usually comprise:
\begin{itemize}
  \item Satellite orbits, clocks, and signal biases
  \item Station positions, clocks, signal biases, and troposphere estimates
  \item Earth orientation parameters
\end{itemize}

A scientific article detailing the underlying processing approach
can be found via DOI \href{https://doi.org/10.1007/s00190-018-1223-2}{10.1007/s00190-018-1223-2}.

An example scenario for this task is available at \url{https://ftp.tugraz.at/outgoing/ITSG/groops/scenario/scenarioGnssNetwork.zip}.
It includes GROOPS scripts and data for the example, but not the general GROOPS data and metadata found at \url{https://ftp.tugraz.at/outgoing/ITSG/groops} (data folder or zipped archive).
The scenario generally represents what is described in this cookbook, but may slightly differ in certain settings.

\emph{Note: Global GNSS processing can become very computationally intensive. Depending on the number of satellites
and stations, the observation and processing sampling, and parametrizations it can quickly exceed the capabilities
of a normal desktop computer and may require computer clusters or number crunchers (see section}
\reference{Parallelization}{general.parallelization}\emph{).}

\subsection{Data preparation}\label{cookbook.gnssNetwork:metadata}
Most of the required metadata files are provided in GROOPS file formats at \url{https://ftp.tugraz.at/outgoing/ITSG/groops}.
These files are regularly updated.

Data that has to be gathered from other sources comprises:
\begin{itemize}
  \item \textbf{Receiver observations}: GNSS measurements converted from RINEX format (see \program{RinexObservation2GnssReceiver}).
  \item \textbf{Approximate orbits}: broadcast or precise orbits in CRF for orbit integration (see \program{GnssRinexNavigation2OrbitClock} or \program{Sp3Format2Orbit}).
  \item \textbf{Approximate clocks}: broadcast or precise clocks (see \program{GnssRinexNavigation2OrbitClock} or \program{GnssClockRinex2InstrumentClock})
\end{itemize}
Receiver observations, broadcast ephemerides, and precise satellite orbits and clocks can be downloaded from the
\href{https://igs.org/data-products-overview/}{IGS Data Centers}.
GPS, GLONASS, and Galileo orbits and clocks for the period 1994-2020 are also available as part of
\href{https://doi.org/10.3217/dataset-4528-0723-0867}{Graz University of Technology's contribution to IGS repro3}.

The \href{https://ftp.tugraz.at/outgoing/ITSG/groops/scenario/scenarioGnssNetwork.zip}{example scenario} includes a small set of this data.
The script \verb|010groopsConvert.xml| can be used to convert these external formats into GROOPS formats.

Prepare a \file{station list file}{stringTable} that contains the stations to be processed.
Each line can contain more than one station. The first station in each line that has data available is used for the processing.
If your network contains more than 60-70 stations, it is recommended to start processing with a core network (see \reference{Advanced}{cookbook.gnssNetwork:advanced}).
In this case, define an additional \file{core station list file}{stringTable} that can also have multiple stations per line.

\subsection{Preprocessing: Orbit integration}\label{cookbook.gnssNetwork:orbitIntegration}
Numerical integration of the satellite orbits is the first step in global GNSS processing.
Dynamic orbits are integrated based on \configClass{force models}{forcesType} and then fitted to the approximate orbits
by estimating their initial state and additional empirical parameters for solar radiation pressure to improve the orbit fit.
The resulting \file{variational equations}{variationalEquation} file contains the integrated orbit, derivatives
with respect to the satellite state vector, attitude, Earth rotation and satellite model.

Orbit preprocessing is covered by the script \verb|020groopsGnssPreprocessing.xml| in the \href{https://ftp.tugraz.at/outgoing/ITSG/groops/scenario/scenarioGnssNetwork.zip}{example scenario}.

It is recommended to perform the steps below in a \reference{loop}{general.loopsAndConditions} over all
satellites/PRNs using \program{LoopPrograms}.

\begin{itemize}
  \item \program{GnssPrn2SvnBlockVariables}
  \item \program{InstrumentResample}: resample approximate orbits from \reference{data preparation}{cookbook.gnssPpp:metadata} to target sampling (e.g., 1 minute) by defining a \configClass{timeSeries}{timeSeriesType} based on a \config{method:polynomial} (\config{polynomialDegree}=\verb|7|, \config{maxDataPointRange}=\verb|7200|, \config{maxExtrapolationDistance}=\verb|900|).
  \item \program{OrbitAddVelocityAndAcceleration}: add velocity via running polynomial (\config{polynomialDegree}=\verb|2|) derivation (needed for attitude computation)
  \item \program{SimulateStarCameraGnss}
  \item \program{PreprocessingVariationalEquation}:
        \begin{itemize}
          \item \configFile{inputfileSatelliteModel}{satelliteModel}=\verb|{groopsDataDir}/gnss/transmitter/satelliteModel/satelliteModel_boxWing.{svn}.xml|
          \item \configFile{inputfileOrbit}{instrument}: the resampled approximate orbit from \program{InstrumentResample}
          \item \configFile{inputfileStarCamera}{instrument}: the attitude file from \program{SimulateStarCameraGnss}
          \item \config{forces}: see below
          \item \configClass{gradientfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}: a static gravity field (e.g. GOCO06s) with \config{maxDegree}=\verb|4|.
        \end{itemize}
  \item \program{PreprocessingVariationalEquationOrbitFit}: fit the integrated orbit (\configFile{inputfileVariational}{variationalEquation}) to the approximate orbit (\configFile{inputfileOrbit}{instrument}) by least squares adjustment.
        Add \configClass{parametrizationAcceleration:gnssSolarRadiation}{parametrizationAccelerationType:gnssSolarRadiation}
        and select the \href{https://doi.org/10.1007/s00190-015-0814-4}{ECOM2} parameters to be estimated.
\end{itemize}

Force models usually include:
\begin{itemize}
  \item \configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}:
        static gravity field (e.g. GOCO06s)
  \item \configClass{gravityfield:trend}{gravityfieldType:trend}
  \begin{itemize}
    \item \configClass{gravityfield:potentialCoefficients}{gravityfieldType:potentialCoefficients}:
          trend component of time-variable gravity field (e.g. GOCO06s)
  \end{itemize}
  \item \configClass{gravityfield:oscillation}{gravityfieldType:oscillation}
  \begin{itemize}
    \item \configClass{gravityfieldCos:potentialCoefficients}{gravityfieldType:potentialCoefficients}:
          annual cosine component of time-variable gravity field (e.g. GOCO06s)
    \item \configClass{gravityfieldSin:potentialCoefficients}{gravityfieldType:potentialCoefficients}:
          annual sine component of time-variable gravity field (e.g. GOCO06s)
  \end{itemize}
  \item \configClass{tides:astronomicalTide}{tidesType:astronomicalTide}: astronomical tides (e.g. based on JPL ephemeris)
  \item \configClass{tides:earthTide}{tidesType:earthTide}: Earth tide (IERS conventions)
  \item \configClass{tides:doodsonHarmonicTide}{tidesType:doodsonHarmonicTide}: ocean tides (e.g. FES 2014b)
  \item \configClass{tides:poleTide}{tidesType:poleTide}: pole tides (IERS conventions)
  \item \configClass{tides:poleOceanTide}{tidesType:oceanPoleTide}: ocean pole tides (IERS conventions)
  \item \configClass{miscAccelerations:solarRadiationPressure}{miscAccelerationsType:solarRadiationPressure}:
        solar radiation pressure (box-wing model)
  \item \configClass{miscAccelerations:albedo}{miscAccelerationsType:albedo}: Earth radiation pressure (albedo model)
  \item \configClass{miscAccelerations:antennaThrust}{miscAccelerationsType:antennaThrust}:
        antenna thrust (e.g. from IGS metadata SINEX file)
  \item \configClass{miscAccelerations:relativisticEffect}{miscAccelerationsType:relativisticEffect}:
        relativistic effects (IERS conventions)
\end{itemize}
For the spherical harmonics expansions a \config{maxDegree}=\verb|60| is more than enough.

The result of the preprocessing should be a \file{variational equations file}{variationalEquation},
a \file{reduced dynamic orbit file}{instrument} from \program{PreprocessingVariationalEquationOrbitFit}
and an \file{attitude file}{instrument} from \program{SimulateStarCameraGnss} for each satellite.

\subsection{GNSS processing}\label{cookbook.gnssNetwork:processing}
The script \verb|030groopsGnssProcessing.xml| in the \href{https://ftp.tugraz.at/outgoing/ITSG/groops/scenario/scenarioGnssNetwork.zip}{example scenario}
implements the following steps and settings.

These are the settings for \program{GnssProcessing}. If not otherwise stated use the default values.

The first step is setting the processing sampling, in this example it is 30~seconds.
The processing interval usually is a single 24-hour day, therefore define
\configClass{timeSeries:uniformSampling}{timeSeriesType:uniformSampling} with \config{timeStart}=\verb|<mjd>|,
\config{timeEnd}=\verb|<mjd>+1|, \config{sampling}=\verb|30/86400| (processing sampling).

Add the appropriate \configClass{transmitters:gnss}{gnssTransmitterGeneratorType:gnss} (e.g. GPS, GLONASS, and Galileo)
and provide the required files:
\begin{itemize}
  \item \configFile{inputfileOrbit}{instrument} from \reference{preprocessing}{cookbook.gnssNetwork:orbitIntegration}
  \item \configFile{inputfileAttitude}{instrument} from \reference{preprocessing}{cookbook.gnssNetwork:orbitIntegration}
  \item \configFile{inputfileClock}{instrument} from \reference{data preparation}{cookbook.gnssPpp:metadata}
\end{itemize}

The following settings are needed in \configClass{receiver:stationNetwork}{gnssReceiverGeneratorType:stationNetwork}:
\begin{itemize}
   \item \configFile{inputfileStationList}{stringTable}: list of all stations to be processed
   \item \configFile{inputfileObservations}{instrument}: The converted RINEX observation files.
   \item \configClass{tidalDisplacement}{tidesType}: Use the settings described in \reference{receiver:stationNetwork}{gnssReceiverGeneratorType:stationNetwork}.
   \item \configClass{excludeType}{gnssType}: Signals you might want to exclude are \verb|C*?G| (old unknown GPS code observations), \verb|*3*R| (GLONASS G3 freq.), \verb|*6*E| (Galileo E6 freq.).
\end{itemize}

Add the following \configClass{parametrizations}{gnssParametrizationType}
and define the \config{outputfiles} you are interested in inside each of them:
\begin{itemize}
  \item \configClass{ionosphereSTEC}{gnssParametrizationType:ionosphereSTEC}: add a constraint of \config{sigmaSTEC}=\verb|40|
  \item \configClass{ionosphereMap}{gnssParametrizationType:ionosphereMap}: add \configClass{temporal:splines}{parametrizationTemporalType:splines}
        with linear (\config{degree}=\verb|1|) 2-hourly splines
  \item \configClass{clocks}{gnssParametrizationType:clocks}: optionally change \configClass{selectTransmitterZeroMeans}{gnssTransceiverSelectorType} to \configClass{wildcard}{gnssTransceiverSelectorType:wildcard} with \config{name}=\verb|G*| to align clocks to mean over GPS (instead of all) satellites
  \item \configClass{signalBiases}{gnssParametrizationType:signalBiases}
  \item \configClass{ambiguities}{gnssParametrizationType:ambiguities}
  \item \configClass{codeBiases}{gnssParametrizationType:codeBiases}
  \item \configClass{tecBiases}{gnssParametrizationType:tecBiases}
  \item \configClass{temporalBias}{gnssParametrizationType:temporalBias}: time-variable GPS L5 phase bias with \configClass{type}{gnssType}=\verb|L5*G|
        and \configClass{parametrizationTemporal:splines}{parametrizationTemporalType:splines} with degree 3 and hourly nodes.
  \item \configClass{staticPositions}{gnssParametrizationType:staticPositions}
  \item \configClass{troposphere}{gnssParametrizationType:troposphere}: select \configClass{troposphere:viennaMapping}{troposphereType:viennaMapping}
        with the appropriate vmf3grid file. Add \configClass{troposphereWetEstimation:splines}{parametrizationTemporalType:splines}
        with linear (\config{degree}=\verb|1|) 2-hourly splines
        and \configClass{troposphereGradientEstimation:splines}{parametrizationTemporalType:splines} with linear daily splines.
  \item \configClass{transmitterDynamicOrbit}{gnssParametrizationType:transmitterDynamicOrbits}:
        provide \configFile{inputfileVariational}{variationalEquation}=\verb|preprocessing/variational.{prn}.dat|
        from the preprocessing step.
        Add \configClass{parametrizationAcceleration:gnssSolarRadiation}{parametrizationAccelerationType:gnssSolarRadiation} and
        \configClass{stochasticPulse:irregular}{timeSeriesType:irregular} parameter at center of day to further improve orbit fit.
  \item \configClass{earthRotation}{gnssParametrizationType:earthRotation}
        \begin{itemize}
          \item \configClass{estimatePole:constant}{parametrizationTemporalType:constant}: polar motion
          \item \configClass{estimatePole:trend}{parametrizationTemporalType:trend} polar motion rate
                (at center of day with \config{timeStep}=\verb|1|)
          \item \configClass{estimateUT1:trend}{parametrizationTemporalType:trend}: length of day (at center of day with
                \config{timeStep}=\verb|-1| to match IGS sign convention)
        \end{itemize}
    \item \configClass{constraints}{gnssParametrizationType:constraints}: loose constraint on GPS L5 phase biases,
        \configClass{parameters:wildcard:type}{parameterSelectorType:wildcard}=\verb|signalBias.L5*|, \config{sigma}=\verb|5| meters, and \config{relativeToApriori}=\verb|yes|
    \item \configClass{constraints}{gnssParametrizationType:constraints}: loose constraint troposphere estimates,
        \configClass{parameters:wildcard:type}{parameterSelectorType:wildcard}=\verb|troposphere*|, \config{sigma}=\verb|5| meters, and \config{relativeToApriori}=\verb|yes|
    \item \configClass{constraints}{gnssParametrizationType:constraints}: constraint on stochastic pulses,
        \configClass{parameters:wildcard:type}{parameterSelectorType:wildcard}=\verb|stochasticPulse*|, \config{sigma}=\verb|0.1| micrometers/second.
\end{itemize}

Finally, define the \configClass{processingSteps}{gnssProcessingStepType}.
This can be overwhelming at first, but offers a lot of flexibility.
The example script uses a 5-minute processing sampling with subsequent clock densification to 30 seconds.

\begin{itemize}
      \item \configClass{selectEpochs}{gnssProcessingStepType:selectEpochs}: with \config{nthEpoch}=\verb|10| to reduce sampling to 5 minutes.
      \item \configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}:
            disable \verb|constraint.STEC|, \verb|*VTEC|, \verb|*.tecBiases| as the ionosphere parameters are estimated in the final steps only.
      \item \configClass{estimate}{gnssProcessingStepType:estimate}: with \config{maxIterationCount}=\verb|6|
      \item \configClass{resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}
      \item \configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}:
            enable \verb|*| (all) parameters
      \item \configClass{estimate}{gnssProcessingStepType:estimate}: with \config{maxIterationCount}=\verb|4|: final iterations (with 5-minute sampling) and ionosphere parameters
      \item \configClass{group}{gnssProcessingStepType:group}: clock densification to 30-second sampling
      \begin{itemize}
            \item \configClass{selectEpochs}{gnssProcessingStepType:selectEpochs}: with \config{nthEpoch}=\verb|1| to set full 30-second sampling
            \item \configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}:
            disable \verb|*| (all) parameters and reenable \verb|*.clock*| and \verb|*.STEC| parameters
            \item \configClass{estimate}{gnssProcessingStepType:estimate}: with \config{maxIterationCount}=\verb|6|
            \item \configClass{writeResults}{gnssProcessingStepType:writeResults}: with \config{suffix}=\verb|30s| to write 30-second clock files
      \end{itemize}
      \item \configClass{writeResults}{gnssProcessingStepType:writeResults}: write the final results
\end{itemize}

With some additional steps, the full 30-second sampling can be used to estimate all parameters (not only the clocks).
These steps are disabled in the example script, as they require at least 16~GB of system memory.
In this case, it is not necessary to separately write the 30-second clock files as listed above.

\begin{itemize}
      \item \configClass{selectEpochs}{gnssProcessingStepType:selectEpochs}: with \config{nthEpoch}=\verb|1| to set full 30-second sampling
      \item \configClass{selectNormalsBlockStructure}{gnssProcessingStepType:selectNormalsBlockStructure}: As the system of normal
      equations can be very large, the memory consumption might be reduced with \config{keepEpochNormalsinMemory}=\verb|no|.
      In this case the epoch parameters are directly eliminated during the accumulation and reconstructed in the solving step.
      This might lead to longer computation times.
      \item \configClass{estimate}{gnssProcessingStepType:estimate}: with \config{maxIterationCount}=\verb|2|: final iterations with full sampling
\end{itemize}

\subsection{Advanced: Processing large station networks}\label{cookbook.gnssNetwork:advanced}

Processing large station networks requires some additional steps to keep the computational load to a reasonable degree.
The general processing strategy is to first process a well-distributed subset of stations (i.e. a core network)
to get good estimates of all satellite parameters, which then enables integer ambiguity resolution (IAR). Once
the ambiguities of the core network are resolved and stable estimates for satellite phase biases are available, all
other (non-core) stations can be processed individually (including IAR) while keeping the satellite parameters fixed.
At last, all stations can be processed together with all satellite parameters and ionosphere parameters.

Let's start with the \configClass{processingSteps}{gnssProcessingStepType} of the core network:
\begin{itemize}
      \item \configClass{selectReceivers}{gnssProcessingStepType:selectReceivers} with \configClass{selectReceivers:file}{gnssTransceiverSelectorType:file}
      using the core network station list file from \reference{data preparation}{cookbook.gnssPpp:metadata} as \configFile{inputfileStringTable}{stringTable}.
      \item \configClass{selectEpochs}{gnssProcessingStepType:selectEpochs}: with \config{nthEpoch}=\verb|10| to reduce sampling to 5 minutes.
      \item \configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}:
            disable \verb|constraint.STEC|, \verb|*VTEC|, \verb|*.tecBiases| as the ionosphere parameters are estimated in the final steps only.
      \item \configClass{estimate}{gnssProcessingStepType:estimate}: with \config{maxIterationCount}=\verb|6|
      \item \configClass{resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}
      \item \configClass{estimate}{gnssProcessingStepType:estimate}: with \config{maxIterationCount}=\verb|4|: final iterations (with 5-minute sampling)
\end{itemize}

Now all other (non-core) stations can be processed separately:
\begin{itemize}
      \item \configClass{forEachReceiverSeparately}{gnssProcessingStepType:forEachReceiverSeparately}:
            with \configClass{selectReceivers:file}{gnssTransceiverSelectorType:file} inside \configClass{selectReceivers:exclude}{gnssTransceiverSelectorType:exclude}
            using the station list from the core network above to process all non-core stations individually with fixed transmitter parameters
      \begin{itemize}
      \item \configClass{processingStep:estimate}{gnssProcessingStepType:estimate}: with \config{maxIterationCount}=\verb|6|
      \item \configClass{processingStep:resolveAmbiguities}{gnssProcessingStepType:resolveAmbiguities}
      \item \configClass{processingStep:estimate}{gnssProcessingStepType:estimate}: with \config{maxIterationCount}=\verb|4|
      \end{itemize}
\end{itemize}

Next all stations are processed together with all parameters:
\begin{itemize}
      \item \configClass{selectReceivers}{gnssProcessingStepType:selectReceivers}: with \configClass{selectReceivers:all}{gnssTransceiverSelectorType:all}
      \item \configClass{selectEpochs}{gnssProcessingStepType:selectEpochs}: with \config{nthEpoch}=\verb|1| to set full 30-second sampling
      \item \configClass{group}{gnssProcessingStepType:group}: clock densification to 30-second sampling
      \begin{itemize}
            \item \configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}:
            disable \verb|*| (all) parameters and reenable \verb|*.clock*| and \verb|*.STEC| parameters
            \item \configClass{estimate}{gnssProcessingStepType:estimate}: with \config{maxIterationCount}=\verb|6|
      \end{itemize}
      \item \configClass{selectParametrizations}{gnssProcessingStepType:selectParametrizations}: enable \verb|*| (all) parameters.
      \item \configClass{selectNormalsBlockStructure}{gnssProcessingStepType:selectNormalsBlockStructure}: with \config{keepEpochNormalsinMemory}=\verb|no|
      \item \configClass{estimate}{gnssProcessingStepType:estimate}: with \config{maxIterationCount}=\verb|4|: final iterations with full sampling and all parameters
      \item \configClass{writeResults}{gnssProcessingStepType:writeResults}: write the final results
\end{itemize}

% =============================================================
